#ifndef AVALON_ASYNCHOLDER_HPP
#define AVALON_ASYNCHOLDER_HPP
#include "Avalon/Threading/Async.hpp"

namespace Avalon {
namespace Threading {

  /*! \class BaseAsyncHolder
   *  \brief Base class of the AsyncHolder.
   */
  class BaseAsyncHolder : private boost::noncopyable {
    public:
      virtual ~BaseAsyncHolder();

      //! Returns the exception held by the Async.
      virtual const boost::exception_ptr& GetException() const = 0;

      //! Sets the exception of the Async held.
      virtual void SetException(const boost::exception_ptr& e) = 0;

      //! Resets the held Async.
      virtual void Reset() = 0;
  };

  /*! \class AsyncHolder
   *  \brief Provides a generic interface for operating on Async's of any type.
   */
  template<typename T>
  class AsyncHolder : public BaseAsyncHolder {
    public:

      //! Constructs an AsyncHolder.
      /*!
        \param async The Async to hold.
      */
      AsyncHolder(Async<T>* async)
          : m_async(async) {}

      virtual ~AsyncHolder() {}

      //! Returns the Async being held.
      Async<T>& GetAsync() {
        return *m_async;
      }

      //! Returns the Async being held.
      const Async<T>& GetAsync() const {
        return *m_async;
      }

      virtual const boost::exception_ptr& GetException() const {
        return m_async->GetException();
      }

      virtual void SetException(const boost::exception_ptr& e) {
        m_async->SetException(e);
      }

      virtual void Reset() {
        m_async->Reset();
      }

    private:
      Async<T>* m_async;
  };
}
}

#endif // AVALON_ASYNCHOLDER_HPP
